package com.code2roc.jarmanage.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.params.ScanParams;
import redis.clients.jedis.resps.ScanResult;
import redis.clients.jedis.resps.Slowlog;
import redis.clients.jedis.resps.Tuple;

import java.util.*;

public class JedisUtil {
    private static JedisPool pool = null;
    private static String jedisTag = null;

    public static JedisPool getConnect(String host, int port, String user, String password) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(20);
        jedisPoolConfig.setMinIdle(0);
        if (!StringUtil.isEmpty(password)) {
            JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 10000, user, password);
            return jedisPool;
        } else {
            JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 10000, user, null);
            return jedisPool;
        }

    }

    public static Jedis getClient() {
        String host = ConfigUtil.getConfigValue("redis", "host");
        int port = ConvertUtil.convert2Int(ConfigUtil.getConfigValue("redis", "port"));
        String user = ConfigUtil.getConfigValue("redis", "user");
        String password = ConfigUtil.getConfigValue("redis", "password");
        if (StringUtil.isEmpty(jedisTag)) {
            pool = getConnect(host, port, user, password);
            jedisTag = host + "|" + port + "|" + user + "|" + password;
            return pool.getResource();
        } else {
            String check = host + "|" + port + "|" + user + "|" + password;
            if (jedisTag.equals(check)) {
                return pool.getResource();
            } else {
                pool = getConnect(host, port, user, password);
                jedisTag = host + "|" + port + "|" + user + "|" + password;
                return pool.getResource();
            }
        }
    }

    public static boolean checkConnect(){
        boolean flag = true;
        String host = ConfigUtil.getConfigValue("redis", "host");
        int port = ConvertUtil.convert2Int(ConfigUtil.getConfigValue("redis", "port"));
        Jedis jedis = new Jedis(host, port);
        try {
            String response = jedis.ping();
            if (response.equalsIgnoreCase("PONG")) {
                flag = true;
            } else {
                flag = false;
            }
        } catch (Exception e) {
            flag = false;
        } finally {
            jedis.close();
        }
        return flag;
    }

    public static boolean setString(String key, String value, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.set(key, value);
            return true;
        } catch (Exception e) {
            LogUtil.error("setStringEx() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static String getString(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.get(key);
        } catch (Exception e) {
            LogUtil.error("getString() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static Long getExpire(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.expireTime(key);
        } catch (Exception e) {
            LogUtil.error("getString() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static Long getTtl(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.ttl(key);
        } catch (Exception e) {
            LogUtil.error("getString() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static String getType(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.type(key);
        } catch (Exception e) {
            LogUtil.error("getString() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }


    public static boolean delString(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.del(key);
            return true;
        } catch (Exception e) {
            LogUtil.error("delString() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean delHash(String key, String mKey, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.hdel(key, mKey);
            return true;
        } catch (Exception e) {
            LogUtil.error("setHash() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean setHash(String key, String mKey, String mVal, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.hset(key, mKey, mVal);
            return true;
        } catch (Exception e) {
            LogUtil.error("setHash() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean setHash(String key, HashMap<String, String> hashMap, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.hset(key, hashMap);
            return true;
        } catch (Exception e) {
            LogUtil.error("setHash() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }


    public static String getHash(String key, String mKey, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.hget(key, mKey);
        } catch (Exception e) {
            LogUtil.error("setHash() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
        return null;
    }

    public static boolean setHashMulti(String key, Map<String, String> map, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.hmset(key, map);
            return true;
        } catch (Exception e) {
            LogUtil.error("setMHash() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static List<String> getHashMulti(String key, String[] members, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.hmget(key, members);
        } catch (Exception e) {
            LogUtil.error("getHashMulti() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
        return null;
    }

    public static List<String> getHashValsAll(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.hvals(key);
        } catch (Exception e) {
            LogUtil.error("getHashValsAll() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
        return null;
    }

    public static Set<String> getHashKeysAll(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            return jedis.hkeys(key);
        } catch (Exception e) {
            LogUtil.error("getHashValsAll() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
        return null;
    }

    public static boolean addScoreSet(String key, String mKey, Double score, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.zadd(key, score, mKey);
            return true;
        } catch (Exception e) {
            LogUtil.error("addScoreSet() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean delScoreSet(String key, String mKey, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.zrem(key, mKey);
            return true;
        } catch (Exception e) {
            LogUtil.error("delScoreSet() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public boolean changeScoreSet(String key, String mKey, int score, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.zincrby(key, score, mKey);
            return true;
        } catch (Exception e) {
            LogUtil.error("changeScoreSet() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }


    public static boolean setList(String key, Object value, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.lpush(key, value.toString());
            return true;
        } catch (Exception e) {
            LogUtil.error("setList() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean setList(String key, List<String> list, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            for (String s : list) {
                jedis.lpush(key, s);
            }
            return true;
        } catch (Exception e) {
            LogUtil.error("setList() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }


    public static boolean setSet(String key, Object value, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            List<String> stringList = (List<String>) value;
            for (String s : stringList) {
                jedis.sadd(key, s);
            }
            return true;
        } catch (Exception e) {
            LogUtil.error("setSet() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static boolean setSet(String key, String value, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.sadd(key, value);
            return true;
        } catch (Exception e) {
            LogUtil.error("setSet() key {} throws:{}", key, e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }


    public static List<String> getList(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            List<String> lrange = jedis.lrange(key, 0, -1);
            return lrange;
        } catch (Exception e) {
            LogUtil.error("getList() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static Set<String> getSet(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            Set<String> smembers = jedis.smembers(key);
            return smembers;
        } catch (Exception e) {
            LogUtil.error("getSet() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }


    public static Map<String, String> getHash(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            Map<String, String> stringStringMap = jedis.hgetAll(key);
            return stringStringMap;
        } catch (Exception e) {
            LogUtil.error("getHash() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static List<Tuple> getZset(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            List<Tuple> tuples = jedis.zrangeWithScores(key, 0, -1);
            return tuples;
        } catch (Exception e) {
            LogUtil.error("getHash() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static void setZset(String key,String value,double socre, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            jedis.zadd(key,socre,value);
        } catch (Exception e) {
            LogUtil.error("setZset() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
    }


    public static Boolean isExist(String key, Jedis jedis, Integer db) {
        try {
            jedis.select(db);
            boolean exists = jedis.exists(key);
            return exists;
        } catch (Exception e) {
            LogUtil.error("getHash() key {} throws:{}", key, e.getMessage());
            return null;
        } finally {
            close(jedis);
        }
    }

    public static void setExpire(String key, Jedis jedis, Long expire, Integer db) {
        try {
            jedis.select(db);
            jedis.expire(key, expire);
        } catch (Exception e) {
            LogUtil.error("setExpire() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
    }

    public static void setExpireAt(String key, Jedis jedis, Long expire, Integer db) {
        try {
            jedis.select(db);
            jedis.expireAt(key, expire);
        } catch (Exception e) {
            LogUtil.error("setExpireAt() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
    }

    public static Boolean updateKeys(Jedis jedis, Integer db, String key, String newKey) {
        try {
            jedis.select(db);
            jedis.rename(key, newKey);
            return true;
        } catch (Exception e) {
            LogUtil.error("updateKeys() key {} throws:{}", e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static void deleteKey(String key,Jedis jedis, Integer db){
        try {
            jedis.select(db);
            jedis.del(key);
        } catch (Exception e) {
            LogUtil.error("deleteKey() key {} throws:{}", key, e.getMessage());
        } finally {
            close(jedis);
        }
    }

    public static List<String> getKeys(String pattern,Jedis jedis, Integer db,boolean autoClose) {
       try{
           jedis.select(db);
           Set<String> keys = jedis.keys(pattern);
           List<String> list = Arrays.asList(keys.toArray(new String[0]));
           return list;
       }catch (Exception e){
           if(autoClose){
               LogUtil.error("getKeys() key {} throws:{}", e.getMessage());
               return null;
           }else{
               throw  e;
           }
       }finally {
           if(autoClose){
               close(jedis);
           }
       }
    }

    public static String getKeyType(Jedis jedis, Integer db, String key,boolean autoClose) {
        try{
            jedis.select(db);
            return jedis.type(key);
        }catch (Exception e){
            if(autoClose){
                LogUtil.error("getKeyType() key {} throws:{}", e.getMessage());
                return "";
            }else{
                throw  e;
            }
        }finally {
            if(autoClose){
                close(jedis);
            }
        }

    }

    public static long getKeyExpire(Jedis jedis, Integer db, String key,boolean autoClose) {
        try {
            jedis.select(db);
            return jedis.ttl(key);
        }catch (Exception e){
            if(autoClose){
                LogUtil.error("getKeyExpire() key {} throws:{}", e.getMessage());
                return -9;
            }else{
                throw  e;
            }
        }finally {
            if(autoClose){
                close(jedis);
            }
        }

    }


    public static Boolean lrem(Jedis jedis, Integer db, String key, String value) {
        try {
            jedis.select(db);
            jedis.lrem(key, 1, value);
            return true;
        } catch (Exception e) {
            LogUtil.error("lrem() key {} throws:{}", e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static Boolean srem(Jedis jedis, Integer db, String key, String value) {
        try {
            jedis.select(db);
            jedis.srem(key, value);
            return true;
        } catch (Exception e) {
            LogUtil.error("srem() key {} throws:{}", e.getMessage());
            return false;
        } finally {
            close(jedis);
        }
    }

    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
}
